package object;

import javax.microedition.khronos.opengles.GL10;

public class TransMatrix {
	public float[] m_untransMat;
	public float[] m_transMat;

	private float m_rotOX = -90f;
	private float m_rotOY = 90f;
	private float m_rotOZ = 0f;
	private float m_angleX = 0f;
	private float m_angleY = 0f;
	private float m_angleZ = 0f;
	private float m_transX = 0f;
	private float m_transY = 0f;
	private float m_transZ = 0f;
	
	private float m_scaleX = 1.0f;
	private float m_scaleY = 1.0f;
	private float m_scaleZ = 1.0f;

	private float one = 75.0f;
	private float[] m_bound = new float[] { 
			-one,	0,		-one,
			one,	0,		-one,
			one,	one,	-one,
			-one,	one,	-one,

			-one,	0,		one,
			one,	0,		one,
			one,	one,	one,
			-one,	one,	one 
		};

	private float xMax;
	private float xMin;
	private float yMax;
	private float yMin;
	private float zMax;
	private float zMin;

	public void SetRotateY(float angle) {
		m_angleY = angle;
		UpdateMatrix();
		UpdateUntransMatrix();
	}
	
	public void SetRotateX(float angle) {
		m_angleX = angle;
		UpdateMatrix();
		UpdateUntransMatrix();
		UpdateMaxMin();
	}
	
	public void SetRotateZ(float angle) {
		m_angleZ = angle;
		UpdateMatrix();
		UpdateUntransMatrix();
		UpdateMaxMin();
	}
	
	public void SetRotateOX(float angle){
		m_rotOX = angle;
		UpdateMatrix();
		UpdateUntransMatrix();
	}
	
	public void SetRotateOY(float angle){
		m_rotOY = angle;
		UpdateMatrix();
		UpdateUntransMatrix();
	}
	
	public void SetRotateOZ(float angle){
		m_rotOZ = angle;
		UpdateMatrix();
		UpdateUntransMatrix();
	}

	public void SetScale(float x, float y, float z) {
		m_scaleX = x;
		m_scaleY = y;
		m_scaleZ = z;
		UpdateMatrix();
		UpdateUntransMatrix();
	}

	public float getTranslateZ() {
		return m_transZ;
	}
	
	public float getTranslateX() {
		return m_transX;
	}

	public float getTranslateY() {
		return m_transY;
	}
	
	public float getRotateOX(){
		return m_rotOX;
	}
	
	public float getRotateOY(){
		return m_rotOY;
	}
	
	public float getRotateOZ(){
		return m_rotOZ;
	}
	
	public float getRotateX(){
		return m_angleX;
	}
	
	public float getRotateY(){
		return m_angleY;
	}
	
	public float getRotateZ(){
		return m_angleZ;
	}
	
	
	public float getScaleX(){
		return m_scaleX;
	}
	
	public float getScaleY(){
		return m_scaleY;
	}
	
	public float getScaleZ(){
		return m_scaleZ;
	}
	private void UpdateUntransMatrix() {

		float[] transMat;

		transMat = getMatrixRotateOX(-m_rotOX);
		m_untransMat = transMat;
		
		transMat = getMatrixRotateOY(-m_rotOY);
		m_untransMat = createtransMatrix(m_untransMat, transMat);
		
		transMat = getMatrixRotateOZ(-m_rotOZ);
		m_untransMat = createtransMatrix(m_untransMat, transMat);
		
		transMat = getMatrixScales(1/m_scaleX, 1/m_scaleY, 1/m_scaleZ);
		m_untransMat = createtransMatrix(m_untransMat, transMat);

		transMat = getMatrixTranslate(-m_transX, -m_transY, -m_transZ);
		m_untransMat = createtransMatrix(m_untransMat, transMat);
		
		transMat = getMatrixRotateOX(-m_angleX);
		m_untransMat = createtransMatrix(m_untransMat, transMat);

		transMat = getMatrixRotateOY(-m_angleY);
		m_untransMat = createtransMatrix(m_untransMat, transMat);
		
		transMat = getMatrixRotateOZ(-m_angleZ);
		m_untransMat = createtransMatrix(m_untransMat, transMat);
	}
	private void UpdateMatrix() {

		float[] transMat;

		transMat = getMatrixRotateOX(m_rotOX);
		m_transMat = transMat;
		
		transMat = getMatrixRotateOY(m_rotOY);
		m_transMat = createtransMatrix(transMat, m_transMat);
		
		transMat = getMatrixRotateOZ(m_rotOZ);
		m_transMat = createtransMatrix(transMat, m_transMat);

		transMat = getMatrixScales(m_scaleX, m_scaleY, m_scaleZ);
		m_transMat = createtransMatrix(transMat, m_transMat);

		transMat = getMatrixTranslate(m_transX, m_transY, m_transZ);
		m_transMat = createtransMatrix(transMat, m_transMat);
		
		transMat = getMatrixRotateOX(m_angleX);
		m_transMat = createtransMatrix(transMat, m_transMat);

		transMat = getMatrixRotateOY(m_angleY);
		m_transMat = createtransMatrix(transMat, m_transMat);
		
		transMat = getMatrixRotateOZ(m_angleZ);
		m_transMat = createtransMatrix(transMat, m_transMat);
	}
	public float[] createtransMatrix(float[] first, float[] second) {
		float[] des = new float[16];
		for (int i = 0; i < 16; i++) {
			int m = i % 4;
			des[i] = first[i - m] * second[m] + 
					first[i - m + 1]* second[m + 4] + 
					first[i - m + 2] * second[m + 8] + 
					first[i - m + 3] * second[m + 12];

		}
		return des;
	}
	public void SetBound(float[] cube)
	{
		for(int i = 0; i < cube.length; ++i)
		{
			m_bound[i] = cube[i];
		}
		this.UpdateMaxMin();
	}
	private void UpdateMaxMin() {
		xMax = m_bound[0];
		xMin = m_bound[0];
		yMax = m_bound[1];
		yMin = m_bound[1];
		zMax = m_bound[2];
		zMin = m_bound[2];
		for (int i = 3; i < 24; i += 3) {
			if (xMax < m_bound[i]) {
				xMax = m_bound[i];
			}
			if (xMin > m_bound[i]) {
				xMin = m_bound[i];
			}

			if (yMax < m_bound[i + 1]) {
				yMax = m_bound[i + 1];
			}
			if (yMin > m_bound[i + 1]) {
				yMin = m_bound[i + 1];
			}

			if (zMax < m_bound[i + 2]) {
				zMax = m_bound[i + 2];
			}
			if (zMin > m_bound[i + 2]) {
				zMin = m_bound[i + 2];
			}
		}

	}

//	public boolean ColliWith(float maxX, float minX, float maxY, float minY,
//			float maxZ, float minZ) {
//		if (this.zMax >= minZ && this.zMin <= maxZ) {
//			if (this.yMax >= minY && this.yMin <= maxY) {
//				if (this.xMax >= minX && this.xMin <= maxX)
//					return true;
//			}
//		}
//
//		return false;
//	}
	public boolean ColliWith(float x, float y, float z) {
		System.out.println("collision xyz" + x + " " + y + " " + z);
		this.UpdateUntransMatrix();
		float point [] = new float[]{x, y, z, 1};
		float des [] = MultMatrix(point, this.m_untransMat);
		System.out.println("collision des" + des[0] + " " + des[1] + " " +des[2] );
		if (this.zMax >= des[2] && this.zMin <= des[2]) {
			if (this.yMax >= des[1] && this.yMin <= des[1]) {
				if (this.xMax >= des[0] && this.xMin <= des[0]){
					System.out.println("collision enemy" + des[0] + " " + des[1] + " " +des[2] );
					return true;
				}
			}
		}
		return false;
	}
//	public boolean ColliWith(float [] point) {
//		if (this.zMax >=point[2] && this.zMin <= point[2]) {
//			if (this.yMax >= point[1] && this.yMin <= point[1]) {
//				if (this.xMax >= point[0] && this.xMin <= point[9])
//					return true;
//			}
//		}
//
//		return false;
//	}

	   public float[] getMatrixRotateOX(float angle)
	    {
	    	float[] temp = new float[16];
	    	for(int i = 0 ; i < 16 ; i ++)
			{
				temp[i] = 0f;
			}
	    	temp[5] = (float)Math.cos(Math.toRadians(angle));
	    	temp[6] = -(float)Math.sin(Math.toRadians(angle));
	    	temp[9] = (float)Math.sin(Math.toRadians(angle));
	    	temp[10] = (float)Math.cos(Math.toRadians(angle));
	    	
	    	temp[0] = 1;
	    	temp[15] = 1;
	    	
	    	return temp;
	    }

	public float[] getMatrixRotateOY(float angle)
	{
   	float[] temp = new float[16];
   	for(int i = 0 ; i < 16 ; i ++)
		{
			temp[i] = 0f;
		}
   	
   	temp[0] = (float)Math.cos(Math.toRadians(angle));
   	temp[2] = (float)Math.sin(Math.toRadians(angle));
   	temp[8] = -(float)Math.sin(Math.toRadians(angle));
   	temp[10] = (float)Math.cos(Math.toRadians(angle));
   	
   	temp[5] = 1;
   	temp[15] = 1;
   	
   	return temp;
   }
	public float[] getMatrixRotateOZ(float angle) {
		float[] temp = new float[16];
		for (int i = 0; i < 16; i++) {
			temp[i] = 0f;
		}
		temp[0] = (float) Math.cos(Math.toRadians(angle));
		temp[1] = -(float) Math.sin(Math.toRadians(angle));
		temp[4] = (float) Math.sin(Math.toRadians(angle));
		temp[5] = (float) Math.cos(Math.toRadians(angle));

		temp[10] = 1;
		temp[15] = 1;
		return temp;
	}

	public float[] getMatrixScales(float x, float y, float z)
	{
		float[] temp = new float[16];
		for(int i = 0 ; i < 16 ; i ++)
		{
			temp[i] = 0f;
		}
		temp[0] = x;
		temp[5] = y;
		temp[10] = z;
		temp[15] = 1;
		return temp;
	}

	public float[] getMatrixTranslate(float x, float y, float z) {
		float[] temp = new float[16];
		for (int i = 0; i < 16; i++) {
			temp[i] = 0f;
		}
		temp[0] = 1;
		temp[5] = 1;
		temp[10] = 1;
		temp[15] = 1;
		temp[3] = x;
		temp[7] = y;
		temp[11] = z;
		return temp;
	}
	
	public float [] MultMatrix(float[] source, float[] trans) {
		float[] des = new float [4];
		for (int i = 0; i < 4; i++) {
			des[i] = (source[0] * trans[i * 4])
					+ (source[1] * trans[(i * 4) + 1])
					+ (source[2] * trans[(i * 4) + 2])
					+ (source[3] * trans[(i * 4) + 3]);
		}
		return des;
	}
	public void TranslateRender(GL10 gl){
		gl.glRotatef(m_angleZ, 0.0f, 0.0f, 1.0f);
		gl.glRotatef(m_angleY, 0.0f, 1.0f, 0.0f);
		gl.glRotatef(m_angleX, 1.0f, 0.0f, 0.0f);

		gl.glTranslatef(m_transX, m_transY, m_transZ);
		
		gl.glScalef(m_scaleX, m_scaleY, m_scaleZ);
		
		gl.glRotatef(m_rotOZ, 0.0f, 0.0f, 1.0f);
		gl.glRotatef(m_rotOY, 0.0f, 1.0f, 0.0f);
		gl.glRotatef(m_rotOX, 1.0f, 0.0f, 0.0f);
	}
	private void printMatrix(float [] matrix){
		for(int i = 0; i <16; i+=4){
			System.out.println(matrix[i]+"\t"+matrix[i+1]+"\t"+matrix[i+2]+"\t"+matrix[i+3]);
		}
		System.out.println();
	}
	public void printMatrix(){
		
		
		this.UpdateMatrix();
		this.UpdateUntransMatrix();
		System.out.println("translate Matrix");
		this.printMatrix(m_transMat);
		
		System.out.println("untranslate Matrix");
		this.printMatrix(m_untransMat);
		System.out.println("test");
		this.printMatrix(this.createtransMatrix(m_transMat, m_untransMat));
	}
	public void setTranslateX(float transX) {
		m_transX = transX;
		UpdateMatrix();
		UpdateUntransMatrix();
	}
	public void setTranslateY(float transY) {
		m_transY = transY;
		UpdateMatrix();
		UpdateUntransMatrix();
	}
	public void SetTranslateZ(float transZ) {
		m_transZ = transZ;
		UpdateMatrix();
		UpdateUntransMatrix();
	}
	public float GetDistance(){
		return (float) Math.sqrt(m_transX*m_transX + m_transY*m_transY + m_transZ*m_transZ);
	}


}
